package top.byfree.jbyan.saber.common.excel

import org.apache.poi.ss.usermodel.BorderStyle
import org.apache.poi.ss.usermodel.WorkbookFactory
import java.io.ByteArrayOutputStream
import java.lang.reflect.Field

/**
 * @author jbyan
 * @since 2024/4/20
 */

inline fun <reified E> toExcel(data: List<E>, colList: List<String>? = emptyList()): ByteArray {
    return WorkbookFactory.create(true).use { workbook ->

        val cellStyle = workbook.createCellStyle()

        cellStyle.borderTop = BorderStyle.MEDIUM
        cellStyle.borderLeft = BorderStyle.MEDIUM
        cellStyle.borderRight = BorderStyle.MEDIUM
        cellStyle.borderBottom = BorderStyle.MEDIUM

        val sheet = workbook.createSheet()

        // 构建表头
        val headerRow = sheet.createRow(0)
        val e = E::class.java
        val declaredFields = e.declaredFields
        var colIndex = 0
        val exportColList = mutableListOf<Field>()
        for (field in declaredFields) {
            // 当前字段被SaberExcel标注，且过滤列表为空，或者当前字段在过滤列表当中
            if (field.isAnnotationPresent(SaberExcel::class.java)
                && (colList.isNullOrEmpty() || colList.contains(field.name))) {
                exportColList.add(field)
                val saberExcel = field.getAnnotation(SaberExcel::class.java)
                sheet.autoSizeColumn(colIndex)
                val createCell = headerRow.createCell(colIndex++)
                createCell.setCellValue(saberExcel.title)
                createCell.cellStyle = cellStyle
            }
        }


        data.forEachIndexed { index, it ->
            val row = sheet.createRow(index + 1)

            exportColList.forEachIndexed { i, field ->
                val createCell = row.createCell(i)
                field.isAccessible = true
                createCell.setCellValue(field.get(it).toString())
                createCell.cellStyle = cellStyle
            }
        }

        val outputStream = ByteArrayOutputStream()
        workbook.write(outputStream)
        // 转化为字节数组
        outputStream.toByteArray()
    }

}